var broker;
var subCounts = {};
var channelMap = {};

function setBroker(newBroker) {
	broker = newBroker;
	broker.on('message', function (channel, message) {
		var sessions = channelMap[channel];
		if (sessions) {
			for (var i = 0, l = sessions.length; i < l; ++i) {
				sessions[i].publish(channel, message);
			}
		}
	});
}

function attach(session) {
	session.on('subscribe', handleSubscribe);
	session.on('unsubscribe', handleUnsubscribe);
	session.on('message', handleMessage);
	session.on('close', handleClose);
}

function remove(session) {
	var channels = session.channels;
	for (var i = 0, l = channels.length; i < l; ++i) {
		handleUnsubscribe.call(session, channels[i]);
	}
	session.removeListener('subscribe', handleSubscribe);
	session.removeListener('unsubscribe', handleUnsubscribe);
	session.removeListener('message', handleMessage);
	session.removeListener('close', handleClose);
}

function handleSubscribe(channel) {
	var sessions = channelMap[channel];
	if (!sessions) {
		sessions = channelMap[channel] = [];
	}
	var index = sessions.indexOf(this);
	if (index >= 0) {
		return;
	}
	if (!++subCounts[channel]) {
		subCounts[channel] = 1;
		broker.subscribe(channel);
	}
	sessions.push(this);
}

function handleUnsubscribe(channel) {
	var sessions = channelMap[channel];
	if (!sessions) {
		return;
	}
	var index = sessions.indexOf(this);
	if (index < 0) {
		return;
	}
	if (!--subCounts[channel]) {
		delete subCounts[channel];
		broker.unsubscribe(channel);
	}
	sessions.splice(index, 1);
}

function handleMessage(channel, message) {
	broker.publish(channel, message);
}

function handleClose() {
	remove(this);
}

exports.attach = attach;
exports.remove = remove;
exports.setBroker = setBroker;
